import { createHashRouter, Navigate } from "react-router";
import { createElement } from "react";
import type { ReactNode } from "react";

// 类型定义
interface RouteMeta {
  layout?: string | boolean; // 允许 layout 为 string 或 boolean 类型
  _isTopLevel?: boolean; // 内部标记，用于在 convertToRoutesArray 中分类
  [key: string]: unknown;
}

// index 字段只能为 true 时用于 index route，否则不要加 index 字段
interface RouteItemBase {
  path: string;
  element: ReactNode;
  handle?: RouteMeta;
  children?: RouteItem[];
}
interface RouteItemIndex {
  index: true;
  element: ReactNode;
  path?: string;
}
type RouteItem = RouteItemBase | RouteItemIndex;

// 类型守卫：判断是否为 RouteItemBase 类型 (即非纯粹的 index 路由)
const isRouteItemBase = (item: RouteItem): item is RouteItemBase => {
  return !("index" in item && item.index === true); // 如果有 index:true，则不是 RouteItemBase
};

// glob 类型
const pages = import.meta.glob<{ default: React.ComponentType<unknown> }>(
  "/src/pages/**/*.{router.tsx,router.jsx}",
  { eager: true }
);
const metas = import.meta.glob<{ default: RouteMeta }>(
  "/src/pages/**/*.meta.{ts,js}",
  { eager: true }
);
const layoutModules = import.meta.glob<{
  default: React.ComponentType<unknown>;
}>("/src/layout/*.tsx", { eager: true });

// layouts 构建
const layouts: Record<
  string,
  React.ComponentType<unknown>
> = Object.fromEntries(
  Object.entries(layoutModules).map(([path, module]) => {
    const name = path.endsWith("/index.tsx")
      ? "DefaultLayout"
      : path.match(/\/layout\/(.*)\.tsx$/)?.[1];
    return [name || "DefaultLayout", module.default];
  })
);
console.log("Constructed Layouts:", layouts);

const generateRoutes = (basePath = "/src/pages"): RouteItem[] => {
  const routeMap: Record<string, RouteItemBase> = {};

  Object.entries(pages).forEach(([path, component]) => {
    const pagePath = path
      .replace(basePath, "")
      .replace(/\/index\.router\.(tsx|jsx)$/, "")
      .toLowerCase();
    // 支持 .meta.ts 和 .meta.js
    const metaPathTs = path.replace(/\.router\.(tsx|jsx)$/, ".meta.ts");
    const metaPathJs = path.replace(/\.router\.(tsx|jsx)$/, ".meta.js");
    const meta = metas[metaPathTs]?.default || metas[metaPathJs]?.default || {};

    const obj: RouteItemBase = {
      path: pagePath,
      element: createElement(component.default),
      handle: meta,
      children: [],
    };

    routeMap[pagePath] = obj;
  });

  const routesArray = convertToRoutesArray(routeMap);
  return routesArray;
};

const convertToRoutesArray = (
  data: Record<string, RouteItemBase>,
  rootRedirect = "/home"
): RouteItem[] => {
  const pathMap = new Map<string, RouteItemBase & { children: RouteItem[] }>();

  for (const path in data) {
    pathMap.set(path, { ...data[path], children: [] });
  }

  // 1. 构建初始层级结构 (rootPaths 包含所有顶层路由及其嵌套子路由)
  const initialRootNodes: RouteItemBase[] = [];
  pathMap.forEach((currentNode, path) => {
    const parentPath = path.substring(0, path.lastIndexOf("/")) || "/";
    if (pathMap.has(parentPath) && path !== parentPath) {
      pathMap.get(parentPath)!.children!.push(currentNode);
    } else {
      initialRootNodes.push(currentNode);
    }
  });

  // 2. 递归处理所有路由，应用 layout 逻辑
  const fullyProcessedRoutes = processRoutes(initialRootNodes, false);

  // 3. 分类最终的顶级路由
  const defaultLayoutChildren: RouteItem[] = []; // 将作为 / 路由的 children
  const topLevelRoutes: RouteItem[] = []; // 将与 / 路由平级

  fullyProcessedRoutes.forEach((item) => {
    // 使用类型守卫确保 item 是 RouteItemBase 类型
    if (!isRouteItemBase(item)) {
      // 如果是 RouteItemIndex 类型 (通常是重定向)，直接将其放入 defaultLayoutChildren
      defaultLayoutChildren.push(item);
      return;
    }

    // 此时 item 已经被类型守卫确定为 RouteItemBase 类型
    const currentItem = item; // 不需要再次断言

    // 检查 _isTopLevel 标记，该标记由 processRoutes 设置
    // 只有明确标记为 _isTopLevel 的才放到 topLevelRoutes
    if (currentItem.handle && currentItem.handle._isTopLevel) {
      topLevelRoutes.push(currentItem);
    } else {
      // 其他所有路由（包括应用了 DefaultLayout 的，或者未指定布局的子路由），
      // 都作为 '/' 路由的 children
      defaultLayoutChildren.push(currentItem);
    }
  });

  const defaultLayout = layouts["DefaultLayout"];

  const finalRoutes: RouteItem[] = [
    {
      path: "/",
      element: defaultLayout // 根路由的 element 始终是默认布局
        ? createElement(defaultLayout, null)
        : createElement("div", null),
      children: [
        {
          // 根路由的重定向作为第一个 index 子路由
          index: true,
          element: <Navigate to={rootRedirect} />,
        },
        ...defaultLayoutChildren, // 其他将由默认布局包裹的子路由
      ],
      handle: {}, // 根路由本身不需要额外的 handle
    } as RouteItemBase,
    ...topLevelRoutes, // 与 / 路由平级的顶级路由
  ];

  return finalRoutes;
};

const processRoutes = (
  routes: RouteItem[],
  isChildRoute: boolean
): RouteItem[] => {
  return routes.map((item) => {
    // 首先对 RouteItem 进行类型守卫，确保后续操作的类型安全
    if (!isRouteItemBase(item)) {
      console.log(
        `Processing (Index Route): isChildRoute: ${isChildRoute}, item:`,
        item
      ); // 日志
      return item; // 如果是纯粹的 index 路由，不进行复杂处理
    }

    const currentItem = { ...item }; // 创建一个可变副本，确保是 RouteItemBase
    console.log(
      `Processing: ${currentItem.path}, isChildRoute: ${isChildRoute}, handle:`,
      currentItem.handle
    ); // 日志

    // 确保 children 数组存在且为数组类型，以便后续操作
    if (!currentItem.children) {
      currentItem.children = [];
    }

    // 确定当前路由是否会应用布局 (无论是指定布局还是默认布局)
    // 这对于向其子路由传递 'isChildRoute' 标志至关重要。
    const willCurrentItemApplyLayout: boolean =
      (currentItem.handle &&
        typeof currentItem.handle.layout === "string" &&
        !!layouts[currentItem.handle.layout]) || // 指定布局存在且可用
      !currentItem.handle ||
      currentItem.handle.layout === undefined; // 没有指定布局或为 undefined，意味着将应用 DefaultLayout（如果可用） // 注意：layout:false 被明确排除，因为它表示不应用布局。

    // 1. 递归处理 children (先处理子路由，这样它们自身的重定向或内部布局可以先应用)
    // 传递 isChildRoute = true 给子路由，如果当前路由已经是子路由，或者当前路由将要应用布局。
    if (currentItem.children.length > 0) {
      console.log(
        `  ${currentItem.path} has children, recursing with isChildRoute: ${
          isChildRoute || willCurrentItemApplyLayout
        }`
      ); // 日志
      currentItem.children = processRoutes(
        currentItem.children,
        isChildRoute || willCurrentItemApplyLayout
      );
    }

    let finalElementForThisRoute = currentItem.element; // 默认是原始页面组件

    // 2. 处理当前路由的重定向逻辑 (如果存在)。
    // 重定向会替换当前路由的 element。
    if (currentItem.handle && currentItem.handle.redirect) {
      console.log(
        `  ${currentItem.path} applying redirect to: ${currentItem.handle.redirect}`
      ); // 日志
      finalElementForThisRoute = createElement(Navigate, {
        to: currentItem.handle.redirect,
      });
      // 重定向已由 element 处理，从 handle 中移除以避免重复处理或混淆
      delete currentItem.handle.redirect;
    }

    // --- 布局应用逻辑 ---

    // 规则 1: layout: false -> 不应用布局，但标记为顶级路由
    if (currentItem.handle && currentItem.handle.layout === false) {
      console.log(
        `  ${currentItem.path} has layout: false, setting _isTopLevel.`
      ); // 日志
      return {
        ...currentItem,
        element: finalElementForThisRoute, // 确保 element 是经过重定向处理后的
        handle: { ...(currentItem.handle || {}), _isTopLevel: true },
      };
    }

    let appliedLayoutModule: React.ComponentType<unknown> | undefined =
      undefined;
    let isTopLevelLayoutApplied = false; // 用于 _isTopLevel 标记，区分是平级还是 / 的 children

    // 只有当当前路由不是子路由时才尝试应用布局
    if (!isChildRoute) {
      // 规则 3: 指定了 layout (string 类型)
      if (currentItem.handle && typeof currentItem.handle.layout === "string") {
        appliedLayoutModule = layouts[currentItem.handle.layout];
        if (appliedLayoutModule) {
          isTopLevelLayoutApplied = true; // 明确指定并找到的布局，标记为顶级路由
          console.log(
            `  ${currentItem.path} applying specific layout: ${currentItem.handle.layout}`
          ); // 日志
        } else {
          console.warn(`未找到布局组件: ${currentItem.handle.layout}`);
          // 如果指定布局未找到，则尝试降级到 DefaultLayout
          appliedLayoutModule = layouts["DefaultLayout"];
          if (appliedLayoutModule) {
            isTopLevelLayoutApplied = false; // DefaultLayout 即使作为降级，也不是"指定"的顶级布局
            console.log(
              `  ${currentItem.path} specified layout not found, falling back to DefaultLayout.`
            ); // 日志
          }
        }
      } else if (
        !currentItem.handle ||
        currentItem.handle.layout === undefined
      ) {
        // 规则 2: 没有指定 layout (undefined)，默认应用 DefaultLayout
        appliedLayoutModule = layouts["DefaultLayout"];
        if (appliedLayoutModule) {
          isTopLevelLayoutApplied = false; // DefaultLayout 总是意味着不是"指定"的顶级布局
          console.log(`  ${currentItem.path} applying DefaultLayout.`); // 日志
        }
      }
    } else {
      console.log(
        `  ${currentItem.path} is a child route, skipping direct layout application.`
      ); // 日志
    }

    if (appliedLayoutModule) {
      // 如果确定要应用布局
      // 当前路由的 element 变为布局组件。
      // 其原始 element (finalElementForThisRoute) 和已处理的 children 会作为布局的子路由。
      const childrenForLayout: RouteItem[] = [
        {
          index: true, // 原始页面/重定向组件作为布局的 index 子路由
          element: finalElementForThisRoute,
        },
        ...(currentItem.children || []), // 保留并附加所有已处理的子路由
      ];
      console.log(`  ${currentItem.path} transformed with layout.`); // 日志

      return {
        ...currentItem, // 保留原始 path, handle (不包含 _isTopLevel) 等
        element: createElement(appliedLayoutModule), // 将 element 替换为布局组件
        children: childrenForLayout, // 更新 children 数组
        handle: {
          ...(currentItem.handle || {}),
          _isTopLevel: isTopLevelLayoutApplied,
        }, // 标记为顶级路由
      } as RouteItemBase;
    } else {
      // 如果当前路由是子路由 (isChildRoute === true)，或者在非子路由情况下没有应用任何布局
      // (例如，指定布局和 DefaultLayout 都未找到)，则直接返回当前项。
      // 确保 element 是经过重定向处理后的。
      console.log(`  ${currentItem.path} returning as is (no layout applied).`); // 日志
      return { ...currentItem, element: finalElementForThisRoute };
    }
  });
};

const routes = generateRoutes();
console.log("Final Routes:", routes);

export const router = createHashRouter(routes);
